Android数据存储(一)SQLite
最近项目需要用到涉及数据库SQLite的知识,真正用的时候才发现自己一点都不熟悉。所以打算将其使用方法总结一下,方便自己以后复习。
demo下载链接:
SQLiteDatabase
SQLiteDatabase类用来管理SQLite数据库。
它有方法可以创建,删除,执行SQL命令,并执行其它常见的数据库管理任务。
1 创建 打开数据库
SQLiteDatabase类中提供了5 个static方法用来打开一个文件对应的数据库。
//openDatabase方法打开path文件对应的数据库。 public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,DatabaseErrorHandler errorHandler) //openOrCreateDatabase 如果不存在则先创建再打开数据库,如果存在则直接打开。 public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory,DatabaseErrorHandler errorHandler)通过文件path 或者file 创建SQLiteDatabase对象。通过此对象就可以操作数据库了。 //创建打开数据库。 SQLiteDatabase mTestDb = SQLiteDatabase.openOrCreateDatabase("/data/data/cn.vn.sqlitedatademo/databases/my.db", null); 要保证文件路径是已存在,(例如没有databases文件夹,则会报错android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database)
Activity的父类(不是直接父类)ContextWrapper.java实现了context.java中的如下两个抽象方法:
SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory)
SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
DatabaseErrorHandler errorHandler)
所以可以在Activity中直接调用这两个方法来创建数据库,或者通过它的context来创建数据库。
2 创建表创建一张表,表名user_info,列为 _id(主键并且自动增加)、name(用户名)、pwd(密码)、modifyTime(修改时间)。
mTestDb.execSQL("CREATE TABLE IF NOT EXISTS user_info(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,pwd TEXT,modifyTime INTEGER)");3 添加数据 public static void InsertTest(){ UserBean user = new UserBean(); user.setName("xiaopihai"); user.setPwd("12345678"); user.setModifyTime(System.currentTimeMillis()); //增加一条数据,INSERT INTO user_info VALUES()因为有4列,所以需要写4项数据,否则会失败, //第一个数据位null,这是因为它是自动增长的。. mTestDb.execSQL("INSERT INTO user_info VALUES(null,'xiaopihai','12345678',"+user.getModifyTime()+")"); //不可以为主键设置数据,因为它是唯一的,不可以与别的相同。否则会报错 //SQLiteConstraintException: PRIMARY KEY must be unique (code 19) //mTestDb.execSQL("INSERT INTO user_info VALUES(12,'zhangsan','mima1111',"+System.currentTimeMillis()+")"); //下面是增加一条数据(只设置某个或某几个内容),默认没添加的数据时空的。 mTestDb.execSQL("INSERT INTO user_info(name,pwd) VALUES('lisi','mimajjjj')"); mTestDb.execSQL("INSERT INTO user_info VALUES(null,?,?,?)",new Object[]{user.getName(),user.getPwd(),user.getModifyTime()}); mTestDb.execSQL("INSERT INTO user_info(name,pwd) VALUES(?,?)",new Object[]{"lisi","mimajjjj"}); ContentValues values = new ContentValues(); values.put(UserSQLiteOpenHelper.COL_NAME,"qwerdf"); //values.put(UserSQLiteOpenHelper.COL_PWD, "qwerdflol"); values.put(UserSQLiteOpenHelper.COL_TIME, user.getModifyTime()); mTestDb.insert("user_info", null,values); }
数据库结果
_id|name|pwd|modifyTime 1|xiaopihai|12345678|1466403447668 2|lisi|mimajjjj| 3|xiaopihai|12345678|1466403447668 4|lisi|mimajjjj| 5|qwerdf||1466403447668数据库增加有两种方法:
(一)通过执行sql语句,调用execSQL(String sql) 或者 execSQL(String sql,Object[] bindArgs)方法。
execSQL(String sql) 执行不带占位符的sql语句
mTestDb.execSQL("INSERT INTO user_info(name,pwd) VALUES('hhohh', 'hidiiiihiihh')");
execSQL(String sql, Object[] bindArgs)执行带占位符的SQL语句。
mTestDb.execSQL("INSERT INTO user_info(name,pwd) VALUES(?,?)",new Object[]{"lisi","mimajjjj"});
(二)SQLiteDatabase的insert(String table,String nullColumnHack,ContentValues values)方法,
参数1 表名称,
参数2 空列的默认值
参数3 ContentValues类型的一个封装了列名称和列值的Map;
返回值:新插入的行的行号,或-1(如果发生错误)。
values中可以存单个或多个数据。
ContentValues values = new ContentValues(); values.put(UserSQLiteOpenHelper.COL_NAME,"qwerdf"); //values.put(UserSQLiteOpenHelper.COL_PWD, "qwerdflol"); values.put(UserSQLiteOpenHelper.COL_TIME, user.getModifyTime()); mTestDb.insert("user_info", null,values);} 4 修改数据 public static void updateTest(){ mTestDb.execSQL("UPDATE user_info SET name = 'update1' WHERE _id = 1;"); mTestDb.execSQL("UPDATE user_info SET name =http://www.it165.net/database/html/201607/? WHERE _id=http://www.it165.net/database/html/201607/?",new Object[]{"update1",1}); mTestDb.execSQL("UPDATE user_info SET name = 'update2',modifyTime=111 WHERE _id = 2;"); mTestDb.execSQL("UPDATE user_info SET name =http://www.it165.net/database/html/201607/? ,modifyTime =http://www.it165.net/database/html/201607/? WHERE _id=http://www.it165.net/database/html/201607/?",new Object[]{"update1",111,2}); ContentValues values = new ContentValues(); values.put("name","update3"); values.put("pwd", "2222222"); values.put("modifyTime", 898); mTestDb.update("user_info", values, "_id=http://www.it165.net/database/html/201607/?", new String[]{String.valueOf(3)}); } 结果: _id|name|pwd|modifyTime 1|update1|12345678|1466404010484 2|update1|mimajjjj|111 3|update3|2222222|898 4|lisi|mimajjjj| 5|qwerdf||1466404010484修改数据库两种方法:
(一)通过execSQL执行sql语句。
(二)通过方法
public int update (String table, ContentValues values, String whereClause, String[] whereArgs)在数据库中更新行的便捷方法。
参数:
更新的表名
map更新的内容。null是有效值将被转换为NULL。
whereClause可选更新时WHERE子句适用。传递null将更新所有行。
返回
受影响的行数,如果没有返回0。
_id|name|pwd|modifyTime 3|update3|2222222|898 4|lisi|mimajjjj| 5|qwerdf||1466404010484
删除数据库的两种方法:
修改数据库两种方法:
(一)通过execSQL执行sql语句。
(二)通过下面方法
public int delete (String table, String whereClause, String[] whereArgs) 参数表的表从删除
whereClause选择时删除WHERE子句适用。传递null将删除所有行。
返回
受影响的行数,返回删除的行数,如果没有返回0。 6 查询数据 public List<UserBean> findAll() { List<UserBean> userList = new ArrayList<UserBean>(); //查询表中的所有数据。 Cursor cursor = mDB.query(UserSQLiteOpenHelper.DATABASE_TABLE_USER, null, null, null, null, null, UserSQLiteOpenHelper.COL_TIME + " desc"); //order by modifytime 降序 if (null != cursor) { while (cursor.moveToNext()) { UserBean user = new UserBean(); user.set_id(cursor.getLong(cursor .getColumnIndex(UserSQLiteOpenHelper.COL_ID))); user.setName(cursor.getString(cursor .getColumnIndex(UserSQLiteOpenHelper.COL_NAME))); user.setPwd(cursor.getString(cursor .getColumnIndex(UserSQLiteOpenHelper.COL_PWD))); user.setModifyTime(cursor.getLong(cursor .getColumnIndex(UserSQLiteOpenHelper.COL_TIME))); userList.add(user); } cursor.close(); } return userList; } //某个或某些查询 //模糊查询 Cursor cursor = mDB.query(UserSQLiteOpenHelper.DATABASE_TABLE_USER, null, UserSQLiteOpenHelper.COL_NAME + " like?"+" and "+UserSQLiteOpenHelper.COL_ID+" >?", new String[] {"%"+name+"%",2+""}, null, null, UserSQLiteOpenHelper.COL_ID + " desc"); // Cursor cursor = mDB.query(UserSQLiteOpenHelper.DATABASE_TABLE_USER, // null, UserSQLiteOpenHelper.COL_NAME + " =http://www.it165.net/database/html/201607/?", // new String[] {name}, null, null, UserSQLiteOpenHelper.COL_ID // + " desc"); //多个条件查询 // Cursor cursor = mDB.query(UserSQLiteOpenHelper.DATABASE_TABLE_USER, // null, UserSQLiteOpenHelper.COL_NAME + " like?"+" and "+UserSQLiteOpenHelper.COL_ID+" >?", // new String[] {"%"+name+"%",2+""}, null, null, UserSQLiteOpenHelper.COL_ID // + " desc");

这是SqliteDatabase提供的几种方法,可以适当选用,进行查询。
SQLiteOpenHelper


SQLiteOpenHelper类(抽象类),一个辅助类来管理数据库的建立和版本管理。
可以创建一个它的子类,实现onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int)以及可选的方法onOpen(SQLiteDatabase),它主要是打开数据库(如果已存在),如果没存在则创建并打开。根据需要进行升级。
对其子类进行初始化时UserSQLiteOpenHelper.getInstance(context),这时并没有建立数据库。
public static UserSQLiteOpenHelper getInstance(Context context) { if (null == mInstance) { mInstance = new UserSQLiteOpenHelper(context); mContext = context; } return mInstance; } private UserSQLiteOpenHelper(Context context) { //这时并没有建立数据库。 super(context, REMOTE_LIVE_DATABASE_NAME, null, version); }看父类SQLiteOpenHelper类源码 public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { this(context, name, factory, version, null); } public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version); mContext = context; mName = name; mFactory = factory; mNewVersion = version; mErrorHandler = errorHandler; }
先是调方法SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version),然后掉到方法SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version),该方法中要求我们传递的version必须大于等于1,否则会报错IllegalArgumentException异常。这个方法中并没有为我们创建并打开数据库,只是存了5个变量的值而已。
那什么时候才会创建数据库呢?
SQliteOpenHelper
public SQLiteDatabase getWritableDatabase() { synchronized (this) { return getDatabaseLocked(true); } } public SQLiteDatabase getReadableDatabase() { synchronized (this) { return getDatabaseLocked(false); } } private SQLiteDatabase getDatabaseLocked(boolean writable) { if (mDatabase != null) { if (!mDatabase.isOpen()) { // Darn! The user closed the database by calling mDatabase.close(). mDatabase = null; } else if (!writable || !mDatabase.isReadOnly()) { // The database is already open for business. return mDatabase; } } if (mIsInitializing) { throw new IllegalStateException("getDatabase called recursively"); } SQLiteDatabase db = mDatabase; try { mIsInitializing = true; if (db != null) { if (writable && db.isReadOnly()) { db.reopenReadWrite(); } } else if (mName == null) { db = SQLiteDatabase.create(null); } else { try { if (DEBUG_STRICT_READONLY && !writable) { final String path = mContext.getDatabasePath(mName).getPath(); db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY, mErrorHandler); } else { db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ? Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0, mFactory, mErrorHandler); } } catch (SQLiteException ex) { if (writable) { throw ex; } Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", ex); final String path = mContext.getDatabasePath(mName).getPath(); db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY, mErrorHandler); } } onConfigure(db); final int version = db.getVersion(); if (version != mNewVersion) { if (db.isReadOnly()) { throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + mName); } db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); if (db.isReadOnly()) { Log.w(TAG, "Opened " + mName + " in read-only mode"); } mDatabase = db; return db; } finally { mIsInitializing = false; if (db != null && db != mDatabase) { db.close(); } } }查看SQLiteOpenHelper源码中,发现只有getDatabaseLocked()中才会创建数据库,也就是第一次调用SQLiteOpenHelper.getWritableDatabase()或SQLiteOpenHelper.getReadableDatabase()时才回真正的创建数据库。此方法创建的数据库地址为:/data/data/包名/databases/
onConfigure(db)
创建数据库后,调用onConfigure(db),这个方法里面可以设置数据库连接的一些参数,如setLocale() 、setMaximumSize()、setForeignKeyConstraintsEnabled()。
onCreate(db)
再向下会走到onCreate(db)方法中,onCreate只在数据库第一次创建的时候会调用,调用之前version = 0,之后就会设置新的version,所以此方法不会再走了。在onCreate()方法中,主要用来创建表。
之后使用时可以通过设置SQLiteOpenHelper 中的mNewVersion,然后调用getReadableDatabase()或getWritableDatabase(),当mNewVersion大于数据库的version,则会调用onUpgrade来升级。而当mNewVersion小于数据库的version,则调用onDwongrade来降级。然后再将此版本号设置为数据库的版本号。
db.setVersion(mNewVersion) 如何设置mNewVersion呢?查看SQLiteOpenHelper中只有构造方法中设置了mNewVersion,所有只能通过这两个方法才可以。(子类调用父类的这两个方法。。)
public SQLiteOpenHelper (Context context, String name, SQLiteDatabase.CursorFactory factory, int version) public SQLiteOpenHelper (Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler)onOpen()每次打开数据库会调用,选用,不是必须的。
demo下载链接:
效果图:

相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/sql/sqlite/10594.shtml
相关文章
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
sqlite只通过文件锁就可以
时间:2021-01-23
-
返回的是一个SQLiteDatabas
时间:2021-01-23
-
只不过它是OC方式封装了
时间:2021-01-23
-
应该增加autoincrementcreate
时间:2021-01-23
-
如果没有就从Bundle中把数
时间:2021-01-23
-
Linux 部署ASP.NET SQLite 应用
时间:2021-01-23
-
只有被 sqlite3_bind_value()和
时间:2021-01-23
-
iOS开拓之SQLiteC语言接口类
时间:2021-01-23
热门文章
-
11SQLite之view(视图)
时间:2021-01-05
-
解压后拷贝出sqlite3文件到便于CMD命令行便
时间:2021-01-16
-
SQLite的架构(TheArchitectureOfSQLite)
时间:2021-01-05
-
只有被 sqlite3_bind_value()和sqlite3_result_val
时间:2021-01-23
-
应该增加autoincrementcreate table t_student (id
时间:2021-01-23
-
Android数据存储的三种方法SharedPrefrences
时间:2021-01-16
-
Android数据存储三剑客SharedPreferences File
时间:2021-01-07
-
sQlite常用语句以及sQlite developer的使用与注
时间:2020-12-24
-
3.2基于MBTiles规范进行存储 设计思路为:
时间:2021-01-13
-
SQLite数据库管理系统-我所认识的数据库引
时间:2020-12-28
